/****************************************************************************
 * Copyright (C) 2012
 * by Dj_Skual
 *
 * This software is provided 'as-is', without any express or implied
 * warranty. In no event will the authors be held liable for any
 * damages arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any
 * purpose, including commercial applications, and to alter it and
 * redistribute it freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you
 * must not claim that you wrote the original software. If you use
 * this software in a product, an acknowledgment in the product
 * documentation would be appreciated but is not required.
 *
 * 2. Altered source versions must be plainly marked as such, and
 * must not be misrepresented as being the original software.
 *
 * 3. This notice may not be removed or altered from any source
 * distribution.
 *
 * gui_banner.cpp
 *
 * for SaveGame Manager GX 2012
 ***************************************************************************/
#include "gui_banner.h"
#include "../Memory/MemTools.h"

#define FRAMEDELAY 6
#define BANNER_ICON_NOCOPY 0x000001
#define BANNER_ICON_BOUNCE 0x000010
#define BANNER_ICON_LOOP   0x000000
#define BANNER_ICON_NOCPYBNC (BANNER_ICON_BOUNCE | BANNER_ICON_NOCOPY)

/****************************************************************************
 * Class GuiSaveBanner
 *
 * To draw a Wii Banner from full banner.bin
 ***************************************************************************/
GuiSaveBanner::GuiSaveBanner(ByteArray &mem)
	: GuiImage()
{
	Init(mem.data());
}

GuiSaveBanner::GuiSaveBanner(u8 *mem)
	: GuiImage()
{
	Init(mem);
}

void GuiSaveBanner::Init(u8 *mem)
{
	if(!mem)
		return;
	
	u8* memory = mem;
	
	tplFile = new TplFile(memory, 0xa0, 0, TPL_FMT_RGB, TPL_WII_BANNER);
	if(!tplFile)
		return;
	
	width = 200;
	height = 62;
	
	texture = new Texture();
	texture->Load(tplFile->Datas());
	
	filecheck = true;
}

GuiSaveBanner::~GuiSaveBanner()
{
	if(tplFile)
		delete tplFile;
	if(texture)
		delete texture;
}

void GuiSaveBanner::Draw()
{
	if(!filecheck ||!IsVisible())
		return;
	
	texture->Render(GetLeft(), GetTop(), GetZPosition(), width, height, imageangle, GetScaleX(), GetScaleY(), GetAlpha());
	
	UpdateEffects();
}

/****************************************************************************
 * Class GuiSaveIcon
 *
 * To draw a Wii Icon from full banner.bin
 ***************************************************************************/
GuiSaveIcon::GuiSaveIcon(ByteArray &mem)
	: GuiImage()
{
	Init(mem.data(), mem.size());
}

GuiSaveIcon::GuiSaveIcon(u8 *mem, u32 len)
	: GuiImage()
{
	Init(mem, len);
}

void GuiSaveIcon::Init(u8 *mem, u32 len)
{
	for (int n = 0; n < MAXFRAMES; n++)
	{
		tplFile[n] = NULL;
		texture[n] = NULL;
	}
	
	if(!mem || len < 8)
		return;
	
	width = 64;
	height = 68;
	
	memcpy(&flags, mem+4, 4);
	memcpy(&animSpeed, mem+8, 2);
	reverseAnim = false;
	currentFrame = 0;
	
	frameCnt = (int)MIN(((len - 0x60a0)/0x1200), MAXFRAMES);
	
	u8* memory = mem;
	u32 offset = 0x60a0;
	
	for (int i = 0; i < frameCnt; i++)
	{
		//!check that there really is data and not just a bunch of 0s
		//!there probably is a faster way to check this, as this could slow shit down when there are a bunch of saves
		//!also, it assumes that if there is an empty image, that there will be no other images after it
		if(MemTools::MemIsEmpty((char*)memory+offset, 0x1200))
		{
			frameCnt = i;
			break;
		}
		
		tplFile[i] = new TplFile(memory, offset, 0, TPL_FMT_RGB, TPL_WII_ICON);
		if(!tplFile[i])
		{
			tplFile[i] = NULL;
			frameCnt = i;
			break;
		}
		
		offset += 0x1200;
		
		texture[i] = new Texture();
		if(!texture[i])
		{
			texture[i] = NULL;
			frameCnt = i;
			break;
		}
		texture[i]->Load(tplFile[i]->Datas());
	}
	counter = 0;
	
	if (frameCnt > 0)
		filecheck = true;
}

GuiSaveIcon::~GuiSaveIcon()
{
	for (int i = 0; i < frameCnt; i++)
	{
		if(tplFile[i])
			delete tplFile[i];
		if(texture[i])
			delete texture[i];
	}
}

void GuiSaveIcon::AdvanceFrame()
{
	if (frameCnt < 2)
		return;
	
	if (flags == BANNER_ICON_NOCPYBNC || flags == BANNER_ICON_BOUNCE)
	{
		if (reverseAnim)
			currentFrame--;
		else
			currentFrame++;
		
		if (currentFrame >= frameCnt - 1)
			reverseAnim = true;
		else if (currentFrame < 1)
			reverseAnim = false;
	}
	else if (++currentFrame >= frameCnt)
		currentFrame=0; 
}

void GuiSaveIcon::Draw()
{
	if(!filecheck || !IsVisible())
		return;
	
	if ((counter >= (animSpeed >> (2 * currentFrame) & 3) * FRAMEDELAY) && (((animSpeed & 3) != 0) && (((animSpeed >> 1 * 2) & 3) != 0)))
	{
		counter = 0;
		AdvanceFrame();
	}
	counter++;
	
	texture[currentFrame]->Render(GetLeft(), GetTop(), GetZPosition(), width, height, imageangle, GetScaleX(), GetScaleY(), GetAlpha());
	
	UpdateEffects();
}

/****************************************************************************
 * Class GuiGCBanner
 *
 * To draw a GC Banner
 ***************************************************************************/
/*GuiGCBanner::GuiGCBanner(u8 *mem, u32 banner_offset, u8 fmt, int w, int h)
{
	if(!mem)
		return;
	
	format = fmt;
	width = w;
	height = h;
	
	u8* memory = mem;
	
	u32 pal_offset = ((format == CARD_BANNER_RGB) ? 0x0000 : banner_offset+0x0c00);
	
	tplFile = new TplFile(memory, banner_offset, pal_offset, format, TPL_GC_BANNER);
	if(!tplFile)
		return;
	
	texture = new Texture();
	texture->Load(tplFile->Datas());
	
	filecheck = true;
}

GuiGCBanner::~GuiGCBanner()
{
	if(tplFile)
		delete tplFile;
	if(texture)
		delete texture;
}

void GuiGCBanner::Draw()
{
	if(!filecheck ||!this->IsVisible())
		return;
	
	float currScale = this->GetScale();
	
	texture->Render(this->GetLeft(), this->GetTop(), width, height, imageangle, widescreen ? currScale*0.80 : currScale, currScale,
					this->GetAlpha(), xx1, yy1, xx2, yy2, xx3, yy3, xx4, yy4);
	
	this->UpdateEffects();
}*/

/****************************************************************************
 * Class GuiGCIcon
 *
 * To draw a GC Icon
 ***************************************************************************/
GuiGCIcon::GuiGCIcon(u8 *mem, std::vector<u32 > &offset, std::vector<u32 > &offset_tlut, u8 speed, u8 fmt, u8 anim, int w, int h)
{
	if(!mem)
		return;
	
	tplformat = fmt;
	animType = anim;
	animSpeed = speed;
	reverseAnim = false;
	currentFrame = 0;
	
	width = w;
	height = h;	
	
	int i = 0;
	frameCnt = 0;
	for(i = 0; i < (int)offset.size(); i++)
	{
		if(offset[i] != 0xffffffff)
			frameCnt++;
	}
	
	u8* memory = mem;
	
	for (i = 0; i < frameCnt; i++)
	{
		tplFile[i] = new TplFile(memory, offset[i], offset_tlut[i], tplformat, TPL_GC_ICON);
		if(!tplFile[i])
		{
			frameCnt = i;
			break;
		}
		
		texture[i] = new Texture();
		texture[i]->Load(tplFile[i]->Datas());
	}
	counter = 0;
	
	if (frameCnt > 0)
		filecheck = true;
}

GuiGCIcon::~GuiGCIcon()
{
	for (int i = 0; i < frameCnt; i++)
	{
		if(tplFile[i])
			delete tplFile[i];
		if(texture[i])
			delete texture[i];
	}
}

void GuiGCIcon::AdvanceFrame()
{
	if ((frameCnt < 2))
		return;
	
	if(animType == CARD_ANIM_BOUNCE)
	{
		if (reverseAnim)
			currentFrame--;
		else
			currentFrame++;
		
		if (currentFrame >= frameCnt - 1)
			reverseAnim = true;
		else if (currentFrame < 1)
			reverseAnim = false;
	}
	else if (++currentFrame >= frameCnt)
		currentFrame = 0;
}

void GuiGCIcon::Draw()
{
	if(!filecheck || !IsVisible() || (animSpeed == CARD_SPEED_END))
		return;
	
	if ((counter >= animSpeed * GC_FRAMEDELAY))
	{
		counter=0;
		AdvanceFrame();
	}
	counter++;
	
	texture[currentFrame]->Render(GetLeft(), GetTop(), GetZPosition(), width, height, imageangle, GetScaleX(), GetScaleY(), GetAlpha());
	
	this->UpdateEffects();
}
